package com.spi.soconversion.util;


import java.io.File;
import java.io.IOException;

import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;

import org.xml.sax.SAXException;

import com.spi.soconversion.base.SOCException;
import com.spi.soconversion.base.handlers.InstallBaseConversionErrorHandler;

/**
 * This class validates all xml files created using existing XSDs for Install Base and Closed and Open Sales Order.
 * <p>
 * Issues:
 * <p>
 * NONE
 * <p>
 * History:
 * <p>
 * <ul>
 * <li>2010.05.09 pk: created
 * </ul>
 *
 * @author Ganesh, SPI (pk)
 */

public class XMLValidator {

	private String d_logFileName;
	private SOCFileWriter d_fileWriter;	
	private String d_xsdPath;
	private String d_fileNameStartsWith;
	private int d_batchNum;
	private InstallBaseConversionErrorHandler errorHandler;
	
	public XMLValidator( String logFileName, SOCFileWriter fileWriter, String xsdPath,String fileNameStartsWith,int batchNum )
	{
		d_logFileName = logFileName;
		d_fileWriter = fileWriter;
		d_xsdPath=xsdPath;
		d_fileNameStartsWith=fileNameStartsWith;	
		d_batchNum=batchNum;
		errorHandler= new InstallBaseConversionErrorHandler(d_logFileName,d_fileWriter);
	}


	public long validateXML(String dirName) throws SOCException
	{
		long result=0;
		File xmlDir = new File(dirName);	
		File[] subDir;

		d_fileWriter.write(d_logFileName, SOCUtility.writeLogMessage(SOCConstants.XML_VALIDATOR_STARTED_PROCESSING));
		subDir =xmlDir.listFiles();

		if(subDir!=null)

		{
			for(int loopCounter=0;loopCounter<subDir.length;loopCounter++)
			{
				File childDir = subDir[loopCounter];
				if(childDir.isDirectory())
				{
					result= result+validateFiles(childDir.getAbsolutePath());
				}
			}
		}
		errorHandler.updateErrors();
		d_fileWriter.write(d_logFileName, SOCUtility.writeLogMessage(SOCConstants.XML_VALIDATOR_ENDED_PROCESSING));
		return result;  
	}

	private long validateFiles(String dirName) throws SOCException
	{
		long result=0;
		File xmlDir = new File(dirName);	
		File [] xmlFiles;
		File [] existingFiles;
		File processFile;
		String goodXMLDir = dirName+SOCConstants.DELIMITER+SOCConstants.DIR_NAME_GOOD_RECORDS;
		File goodXMLDirRef= new File(goodXMLDir);
		String badXMLDir = dirName+SOCConstants.DELIMITER+SOCConstants.DIR_NAME_BAD_RECORDS;
		File badXMLDirRef= new File(badXMLDir);

		if (goodXMLDirRef.exists())
		{
			existingFiles =goodXMLDirRef.listFiles();
			for(int loopCounter=0;loopCounter<existingFiles.length;loopCounter++)
			{
				existingFiles[loopCounter].delete();
			}

			goodXMLDirRef.delete();
			existingFiles=null;
			d_fileWriter.write(d_logFileName, SOCUtility.writeLogMessage(SOCConstants.MESSAGE_GOOD_XML_DIRECTORY_CONTENTS_DELETED+
					goodXMLDir)); 
		}

		if (badXMLDirRef.exists())
		{
			existingFiles =badXMLDirRef.listFiles();
			for(int loopCounter=0;loopCounter<existingFiles.length;loopCounter++)
			{
				existingFiles[loopCounter].delete();
			}

			badXMLDirRef.delete();
			d_fileWriter.write(d_logFileName, SOCUtility.writeLogMessage(SOCConstants.MESSAGE_BAD_XML_DIRECTORY_CONTENTS_DELETED+
					badXMLDir)); 
		}


		// get xml schema factory
		SchemaFactory factory = SchemaFactory.newInstance( SOCConstants.XML_SCHEMA);

		// create schema by reading it from an XSD file:
		Schema schema=null;

		try {
			schema = factory.newSchema(new File(d_xsdPath));
		} catch (SAXException saxe) {
			d_fileWriter.write(d_logFileName, SOCUtility.writeLogMessage(ErrorMessageReader.getError(
					ErrorConstants.FAILED_SCHEMA_LOAD_FROM_XSD)+d_xsdPath+SOCConstants.NEW_LINE+saxe.getMessage()));
			throw new SOCException(
					ErrorMessageReader.getError(
							ErrorConstants.FAILED_SCHEMA_LOAD_FROM_XSD)+d_xsdPath,saxe);
		}
		XMLFileFilter xmlFileFilter = new XMLFileFilter(d_fileNameStartsWith, SOCConstants.XML_FILE_EXTN.substring(1));	    
		xmlFiles =xmlDir.listFiles(xmlFileFilter);

		if(xmlFiles.length>0)
		{
			goodXMLDirRef.mkdir();
			badXMLDirRef.mkdir();
		}    
		Validator validator = schema.newValidator();

		// at last perform validation:

			boolean moved;
		for(int loopCounter=0;loopCounter<xmlFiles.length;loopCounter++)
		{

			processFile = xmlFiles[loopCounter];
			String fileName = processFile.getName();
			fileName = fileName.substring(fileName.indexOf(SOCConstants.UNDERSCORE)+1, fileName.indexOf(SOCConstants.DOT));

			try
			{
				validator.validate(new StreamSource(processFile.getPath()));
			}
			catch (SAXException saxe) 
			{
				moved=processFile.renameTo(new File(badXMLDirRef.getPath(), processFile.getName()));
				if(!moved)
				{
					d_fileWriter.write(d_logFileName, SOCUtility.writeLogMessage(ErrorMessageReader.getError(
							ErrorConstants.FAILED_FILE_MOVE_TO_BAD_XML_DIRECTORY)+processFile.getName()+SOCConstants.NEW_LINE+saxe.getMessage()));
					throw new SOCException(
							ErrorMessageReader.getError(
									ErrorConstants.FAILED_FILE_MOVE_TO_BAD_XML_DIRECTORY)+processFile.getName(),saxe);
				}
				d_fileWriter.write(d_logFileName, SOCUtility.writeLogMessage(ErrorMessageReader.getError(
						ErrorConstants.FAILED_XML_VALIDATION_WITH_SAX_PARSER_EXCEPTION)+processFile.getName()));
				errorHandler.addErrors(Long.parseLong(fileName), saxe.getMessage(), d_batchNum);
				continue;

			} catch (IOException ioe) {
				
				moved=processFile.renameTo(new File(badXMLDirRef.getPath(), processFile.getName()));
				if(!moved)
				{
					d_fileWriter.write(d_logFileName, SOCUtility.writeLogMessage(ErrorMessageReader.getError(
							ErrorConstants.FAILED_FILE_MOVE_TO_BAD_XML_DIRECTORY)+processFile.getName()+SOCConstants.NEW_LINE+ioe.getMessage()));
					throw new SOCException(
							ErrorMessageReader.getError(
									ErrorConstants.FAILED_FILE_MOVE_TO_BAD_XML_DIRECTORY)+processFile.getName(),ioe);
				}
				d_fileWriter.write(d_logFileName, SOCUtility.writeLogMessage(ErrorMessageReader.getError(
						ErrorConstants.FAILED_XML_VALIDATION_WITH_IO_EXCEPTION)+processFile.getName()+SOCConstants.NEW_LINE+ioe.getMessage()));
				errorHandler.addErrors(Long.parseLong(fileName), ioe.getMessage(), d_batchNum);
				continue;
			}

			moved=processFile.renameTo(new File(goodXMLDirRef, processFile.getName()));

			if(!moved)
			{
				d_fileWriter.write(d_logFileName, SOCUtility.writeLogMessage(ErrorMessageReader.getError(
						ErrorConstants.FAILED_FILE_MOVE_TO_GOOD_XML_DIRECTORY)+processFile.getName()));
				throw new SOCException(
						ErrorMessageReader.getError(
								ErrorConstants.FAILED_FILE_MOVE_TO_GOOD_XML_DIRECTORY)+processFile.getName());
			}
			result++;
		}
		return result;
	}
} 


